package de.blitzcoder.collide.gui.fileexplorer;

import java.io.File;
import java.io.FilenameFilter;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;

/**
 *
 * @author blitzcoder
 */
public class FileSystemNode implements MutableTreeNode,Serializable {

    private File file;
    private Object userObject;
    private MutableTreeNode parent;
    private File[] children;
    private FileSystemNode[] childNodes;
    
    public FileSystemNode(File file) {
        this.file = file;
        setUserObject(null);
        setParent(null);
    }

    // This node represents a directory, nothing has to be inserted or removed
    public void insert(MutableTreeNode child, int index) {
        throw new UnsupportedOperationException("Nothing to insert");
    }
    public void remove(int index) {
        throw new UnsupportedOperationException("Nothing to remove");
    }
    public void remove(MutableTreeNode node) {
        throw new UnsupportedOperationException("Nothing to remove");
    }
    public void removeFromParent() {
        throw new UnsupportedOperationException("Nothing to do...");
    }
    
    public void setUserObject(Object object) {
        this.userObject = object;
    }

    public void setParent(MutableTreeNode newParent) {
        this.parent = newParent;
    }

    public TreeNode getChildAt(int childIndex) {
        getChildren();
        return childNodes[childIndex];
    }

    public int getChildCount() {
        return getChildren().length;
    }

    public String toString() {
        if (file.getName().length() == 0)
            return file.getAbsolutePath(); // System Roots ("C:\","D:\","/")
        return file.getName();
    }
    
    public File getFile() {
        return file;
    }
    
    /*
     * Returns an File[] of all children (directorys only)
     */
    private File[] getChildren() {
        
        if (children != null)
            return children;

        //new Throwable().printStackTrace();
        children = file.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                if (new File(dir,name).isDirectory())
                    if (!name.startsWith("."))
                        return true;
                return false;
            }
        });

        if (children == null)
            children = new File[0];

        // Sort by name
        Comparator<File> c = new Comparator<File>() {
            public int compare(File o1, File o2) {
                return o1.getName().compareTo(o2.getName());
            }
        };
        Arrays.sort(children, c);

        childNodes = new FileSystemNode[children.length];
        for (int i=0;i<children.length;i++)
            childNodes[i] = new FileSystemNode(children[i]);
        
        return children;
    }
    
    public TreeNode getParent() {
        return parent;
    }

    public int getIndex(TreeNode child) {
        
        // Nobody knows why this is needed
        // Whatever, just perform real check
        // if children data have been cached
        // already
        if (children == null)
            return -1;
        
        if (child instanceof FileSystemNode) {
            FileSystemNode node = (FileSystemNode)child;
            File[] children = getChildren();
            int i = -1;
            for (File file:children) {
                i++;
                if (node.getFile().equals(file)) 
                    return i;
            }
        }
        
        return -1;
    }

    public boolean getAllowsChildren() {
        return true;
    }

    public boolean isLeaf() {
        return false;
    }

    public Enumeration children() {
        final File[] children = getChildren();
        return new Enumeration() {

            int index = 0;
            
            public boolean hasMoreElements() {
                return children.length > index+1;
            }

            public Object nextElement() {
                index++;
                return childNodes[index-1];
            }
        };
    }
    
    public boolean equals(Object node) {
        if (node instanceof FileSystemNode)
            return ((FileSystemNode)node).getFile().equals(file);
        return false;
    }
    
}
